/**
 * 速算题目生成器
 */
import QuestionGeneratorBase from './question-generator-base.js';

class SpeedCalcGenerator extends QuestionGeneratorBase {
    /**
     * 生成速算题目
     * @param {Object} options 选项配置
     * @returns {Array} 题目数组
     */
    static generateQuestions(options = {}) {
        const {
            count = 10,
            operations = ['add', 'subtract', 'multiply', 'divide'],
            valueTypes = ['integer', 'decimal'],
            digitRange = {min: 2, max: 5}
        } = options;

        const questions = [];

        for (let i = 0; i < count; i++) {
            const operation = operations[Math.floor(Math.random() * operations.length)];
            const valueType = valueTypes[Math.floor(Math.random() * valueTypes.length)];

            const question = this.generateSingleCalcQuestion(operation, valueType, digitRange);
            questions.push({
                ...question,
                id: `calc_${Date.now()}_${i}`,
                index: i + 1
            });
        }

        return questions;
    }

    /**
     * 生成单个速算题目
     * @param {string} operation 运算类型
     * @param {string} valueType 数值类型
     * @param {Object} digitRange 位数范围
     * @returns {Object} 题目对象
     */
    static generateSingleCalcQuestion(operation, valueType, digitRange) {
        let operand1, operand2, answer, question;
        let attempts = 0;
        const maxAttempts = 10;

        // 根据运算类型调整位数范围，确保结果不超过5位
        let adjustedDigitRange = {...digitRange};

        // 对于乘法，限制更严格，避免结果超过5位
        if (operation === 'multiply') {
            adjustedDigitRange.max = Math.min(3, digitRange.max); // 乘法最多3位数
        } else {
            adjustedDigitRange.max = Math.min(4, digitRange.max); // 其他运算最多4位数
        }

        // 限制最小值
        adjustedDigitRange.min = Math.min(adjustedDigitRange.min, adjustedDigitRange.max);

        // 尝试生成符合条件的题目
        do {
            attempts++;

            switch (valueType) {
                case 'integer':
                    [operand1, operand2] = this.generateIntegers(adjustedDigitRange);
                    break;
                case 'decimal':
                    [operand1, operand2] = this.generateDecimals(adjustedDigitRange);
                    break;
                case 'percentage':
                    [operand1, operand2] = this.generatePercentages(adjustedDigitRange);
                    break;
                default:
                    [operand1, operand2] = this.generateIntegers(adjustedDigitRange);
            }

            switch (operation) {
                case 'add':
                    answer = operand1 + operand2;
                    question = `${this.formatOperandForDisplay(operand1, valueType)} + ${this.formatOperandForDisplay(operand2, valueType)}`;
                    break;
                case 'subtract':
                    // 确保结果为正数
                    if (operand1 < operand2) {
                        [operand1, operand2] = [operand2, operand1];
                    }
                    answer = operand1 - operand2;
                    question = `${this.formatOperandForDisplay(operand1, valueType)} - ${this.formatOperandForDisplay(operand2, valueType)}`;
                    break;
                case 'multiply':
                    answer = operand1 * operand2;
                    question = `${this.formatOperandForDisplay(operand1, valueType)} × ${this.formatOperandForDisplay(operand2, valueType)}`;
                    break;
                case 'divide':
                    // 除数已经在生成操作数时确保不为0了
                    answer = operand1 / operand2;

                    // 如果结果小数位数过多，最多保留2位小数
                    if (this.countDecimalPlaces(answer) > 2) {
                        answer = this.formatNumber(answer)
                    }
                    question = `${this.formatOperandForDisplay(operand1, valueType)} ÷ ${this.formatOperandForDisplay(operand2, valueType)}`;
                    break;
                default:
                    answer = operand1 + operand2;
                    question = `${this.formatOperandForDisplay(operand1, valueType)} + ${this.formatOperandForDisplay(operand2, valueType)}`;
            }

            // 检查答案的整数部分是否超过5位
            const integerPart = Math.floor(Math.abs(answer));

            // 如果答案合法或尝试次数过多，退出循环
            if (integerPart >= 100000) {
                // 如果尝试多次仍超过5位，强制调整
                const scale = Math.ceil(integerPart / 99999);
                operand1 = this.roundToDecimalPlaces(operand1 / scale, 2);
                operand2 = this.roundToDecimalPlaces(operand2 / scale, 2);

                // 重新计算
                switch (operation) {
                    case 'add':
                        answer = operand1 + operand2;
                        break;
                    case 'subtract':
                        answer = Math.abs(operand1 - operand2);
                        break;
                    case 'multiply':
                        answer = operand1 * operand2;
                        break;
                    case 'divide':
                        answer = operand2 !== 0 ? operand1 / operand2 : operand1;
                        break;
                }

                // 重新生成问题字符串
                switch (operation) {
                    case 'add':
                        question = `${this.formatOperandForDisplay(operand1, valueType)} + ${this.formatOperandForDisplay(operand2, valueType)}`;
                        break;
                    case 'subtract':
                        question = `${this.formatOperandForDisplay(operand1, valueType)} - ${this.formatOperandForDisplay(operand2, valueType)}`;
                        break;
                    case 'multiply':
                        question = `${this.formatOperandForDisplay(operand1, valueType)} × ${this.formatOperandForDisplay(operand2, valueType)}`;
                        break;
                    case 'divide':
                        question = `${this.formatOperandForDisplay(operand1, valueType)} ÷ ${this.formatOperandForDisplay(operand2, valueType)}`;
                        break;
                }
            } else {
                break
            }
        } while (attempts < maxAttempts);

        return {
            question,
            answer: this.roundToDecimalPlaces(answer, 2),
            operand1,
            operand2,
            operation,
            valueType,
            userAnswer: null,
            isCorrect: null,
            timeUsed: 0
        };
    }

    /**
     * 生成整数
     */
    static generateIntegers(digitRange) {
        let operand1, operand2;
        let attempts = 0;
        const maxAttempts = 20;

        do {
            operand1 = this.generateRandomNumberForCalc(digitRange.min, digitRange.max, 'integer');
            operand2 = this.generateRandomNumberForCalc(digitRange.min, digitRange.max, 'integer');
            attempts++;

            // 检查两个操作数是否相差超过100倍以及两个操作数是否都小于等于0
            const ratio1 = Math.max(operand1, operand2) / Math.min(operand1, operand2);
            if (ratio1 <= 100 && !operand1 <= 0 && !operand2 <= 0) {
                break;
            }
        } while (attempts < maxAttempts);

        return [operand1, operand2];
    }

    /**
     * 生成小数
     */
    static generateDecimals(digitRange) {
        let operand1, operand2;
        let attempts = 0;
        const maxAttempts = 20;

        do {
            operand1 = this.generateRandomNumberForCalc(digitRange.min, digitRange.max, 'decimal');
            operand2 = this.generateRandomNumberForCalc(digitRange.min, digitRange.max, 'decimal');
            attempts++;

            // 检查两个操作数是否相差超过100倍以及两个操作数是否都小于等于0
            const ratio1 = Math.max(operand1, operand2) / Math.min(operand1, operand2);
            if (ratio1 <= 100 && !operand1 <= 0 && !operand2 <= 0) {
                break;
            }
        } while (attempts < maxAttempts);

        return [operand1, operand2];
    }

    /**
     * 生成百分数
     */
    static generatePercentages(digitRange) {
        let operand1, operand2;
        let attempts = 0;
        const maxAttempts = 20;

        do {
            operand1 = this.generateRandomNumberForCalc(digitRange.min, digitRange.max, 'percentage');
            operand2 = this.generateRandomNumberForCalc(digitRange.min, digitRange.max, 'percentage');
            attempts++;

            // 检查两个操作数是否相差超过100倍以及两个操作数是否都小于等于0
            const ratio1 = Math.max(operand1, operand2) / Math.min(operand1, operand2);
            if (ratio1 <= 100 && !operand1 <= 0 && !operand2 <= 0) {
                break;
            }
        } while (attempts < maxAttempts);

        return [operand1, operand2];
    }

    /**
     * 生成指定范围的随机数（速算用）
     * @param {number} minDigits 最小位数
     * @param {number} maxDigits 最大位数
     * @param {string} type 数值类型
     */
    static generateRandomNumberForCalc(minDigits, maxDigits, type = 'integer') {
        // 限制最大位数不超过5位
        const effectiveMaxDigits = Math.min(maxDigits, 5);
        const effectiveMinDigits = Math.min(minDigits, effectiveMaxDigits);

        const digits = Math.floor(Math.random() * (effectiveMaxDigits - effectiveMinDigits + 1)) + effectiveMinDigits;
        const min = Math.pow(10, digits - 1);
        const max = Math.pow(10, digits) - 1;

        let number = Math.floor(Math.random() * (max - min + 1)) + min;

        if (type === 'decimal') {
            // 确保生成0-2位小数
            const decimalPlaces = Math.floor(Math.random() * 3); // 0-2位小数
            if (decimalPlaces > 0) {
                number = number / Math.pow(10, decimalPlaces);
            }
        } else if (type === 'percentage') {
            number = number / 100; // 转换为百分数形式的小数
        }

        return this.roundToDecimalPlaces(number, 2);
    }
}

export default SpeedCalcGenerator;

